home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Halma 1.1.source Folder / Halma ƒ / Shell ƒ / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-25  |  11.6 KB  |  358 lines  |  [TEXT/KAHL]

  1. /**********************************************************************\
  2.  
  3. File:        main.c
  4.  
  5. Purpose:    This module handles the event loop and event dispatching.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program in a file named "GNU General Public License".
  19. If not, write to the Free Software Foundation, 675 Mass Ave,
  20. Cambridge, MA 02139, USA.
  21.  
  22. \**********************************************************************/
  23.  
  24. #include "graphics.h"
  25. #include "main.h"
  26. #include "apple events.h"
  27. #include "integrity.h"
  28. #include "about.h"
  29. #include "help.h"
  30. #include "menus.h"
  31. #include "prefs.h"
  32. #include "environment.h"
  33. #include "progress.h"
  34. #include "error.h"
  35. #include "sounds.h"
  36. #include "halma.h"
  37. #include "program globals.h"
  38.  
  39. void main(void)
  40. {
  41.     Boolean            programIntegrityVerified;
  42.     Boolean            programIntegritySet;
  43.     
  44.     /* do integrity check before anything else; see integrity.c for details */
  45.     programIntegrityVerified=DoIntegrityCheck(&programIntegritySet);
  46.     
  47.     /* standard program initialization stuff */
  48.     MaxApplZone();    
  49.     InitGraf(&thePort);
  50.     InitFonts();
  51.     FlushEvents(everyEvent, 0);
  52.     InitWindows();
  53.     InitMenus();
  54.     TEInit();
  55.     InitDialogs(0L);
  56.     InitCursor();
  57.     GetDateTime((unsigned long*)&randSeed);
  58.     
  59.     if (!InitTheEnvironment())            /* gestalt checks and variable initialization */
  60.         HandleError(kSystemTooOld, TRUE);        /* less than system 4.1 */
  61.     
  62.     if (!programIntegrityVerified)    /* integrity check failed */
  63.         HandleError(kProgramIntegrityNotVerified, TRUE);
  64.     
  65.     if (programIntegritySet)    /* integrity check freshly installed */
  66.         HandleError(kProgramIntegritySet, FALSE);
  67.     
  68.     if (!InitTheMenus())        /* get menus from .rsrc and draw menu bar */
  69.         HandleError(kProgramIntegrityNotVerified, TRUE);
  70.         
  71.     InitTheSounds();                /* see if sound is available, etc. */
  72.     
  73.     PrefsError(PreferencesInit());    /* get prefs (create if necessary) */
  74.     
  75.     if (!InitTheGraphics())        /* initialize offscreen gworlds/bitmaps, etc */
  76.         HandleError(kNoMemoryAndQuitting, TRUE);
  77.     
  78.     InitTheProgram();                /* program-specific initialization */
  79.     
  80.     EventLoop();                    /* where it all happens (see below) */
  81.     
  82.     ShutDownEnvironment();            /* where it all ends (see below) */
  83.     
  84.     ExitToShell();
  85. }
  86.  
  87. void EventLoop(void)
  88. {
  89.     while (!gDone)    /* gDone set by choosing "Quit" menu item or by "quit" apple event */
  90.         HandleSingleEvent();
  91. }
  92.  
  93. Boolean HandleSingleEvent(void)
  94. {
  95.     EventRecord        theEvent;
  96.     short            i;
  97.     
  98.     SetCursor(&arrow);        /* should set once every time through event loop */
  99.     HiliteMenu(0);            /* normalize menubar */
  100.     
  101.     gFrontWindowIsOurs=FALSE;
  102.     if (FrontWindow()!=0L)    /* if there's a front window, see if it's one of ours */
  103.     {
  104.         for (i=0; ((i<NUM_WINDOWS) && (!gFrontWindowIsOurs)); i++)
  105.         {
  106.             if (FrontWindow()==gTheWindow[i])    /* found one of ours, so SetPort */
  107.             {
  108.                 SetPort(gTheWindow[i]);
  109.                 gFrontWindowIsOurs=TRUE;
  110.             }
  111.         }
  112.     }
  113.         
  114.     /* get an event from the queue */
  115.     GetTheEvent(&theEvent, gIsInBackground ? gBackgroundWaitTime : gForegroundWaitTime);
  116.     
  117.     DispatchEvents(theEvent);    /* handle the event we just got */
  118.     
  119.     return (theEvent.what!=nullEvent);
  120. }
  121.  
  122. void GetTheEvent(EventRecord *theEvent, short waitTime)
  123. {
  124.     if (gWaitNextEventAvailable)
  125.         WaitNextEvent(everyEvent, theEvent, waitTime, 0L);
  126.     else
  127.     {
  128.         GetNextEvent(everyEvent, theEvent);
  129.         SystemTask();
  130.     }
  131. }
  132.  
  133. void DispatchEvents(EventRecord theEvent)
  134. {
  135.     short            i;
  136.     Point            thisPoint;
  137.     short            index;
  138.     unsigned long    dummy;
  139.     WindowPtr        theWindow;
  140.     Boolean            thisWindowIsOurs;
  141.     ExtendedWindowDataHandle
  142.                     theData;
  143.     
  144.     thisWindowIsOurs=FALSE;
  145.     /* for update/activate events, see if the window in question is one of ours */
  146.     if ((theEvent.what==activateEvt) || (theEvent.what==updateEvt))
  147.     {
  148.         for (i=0; ((i<NUM_WINDOWS) && (!thisWindowIsOurs)); i++)
  149.             thisWindowIsOurs=((WindowPtr)theEvent.message==gTheWindow[i]);
  150.     }
  151.  
  152.     if (thisWindowIsOurs)    /* for activate/update events, get window data structure */
  153.     {
  154.         theData=(ExtendedWindowDataHandle)GetWRefCon((WindowPtr)theEvent.message);
  155.         index=(**theData).windowIndex;
  156.     }
  157.     else if (gFrontWindowIsOurs)    /* if front window is ours, get window data struct */
  158.     {
  159.         theData=(ExtendedWindowDataHandle)GetWRefCon(FrontWindow());
  160.         index=(**theData).windowIndex;
  161.     }
  162.     else index=-1;
  163.     
  164.     switch (theEvent.what)
  165.     {
  166.         case nullEvent:    /* ain't nuthin' happenin' */
  167.             if ((gSoundAvailable) && (gSoundIsFinishedPlaying))
  168.                 CloseTheSoundChannel();
  169.             if (gFrontWindowIsOurs)        /* give control to window dispatch to handle null */
  170.                 ((**theData).dispatchProc)((WindowDataHandle)theData, kNull, 0L);
  171.             break;
  172.         case mouseDown:    /* mouse button pressed */
  173.             HandleMouseDown(theEvent);    /* see below for mousedown handling */
  174.             break;
  175.         case keyDown:    /* key pressed */
  176.         case autoKey:    /* key help down */
  177.             if (theEvent.modifiers & cmdKey)    /* handle as command-key equivalent */
  178.             {
  179.                 AdjustMenus();    /* just to be safe */
  180.                 /* get the menu ID + item and handle it as a menu choice */
  181.                 HandleMenu(MenuKey((char)(theEvent.message & charCodeMask)));
  182.             }
  183.             else if (gFrontWindowIsOurs)    /* --> window's dispatch for keydown */
  184.                 ((**theData).dispatchProc)((WindowDataHandle)theData, kKeydown, theEvent.message);
  185.             break;
  186.         case diskEvt:    /* disk insert */
  187.             if (HiWord(theEvent.message)!=noErr)    /* bad disk inserted */
  188.             {
  189.                 DILoad();    /* load disk initialization package */
  190.                 SetPt(&thisPoint, 120, 120);
  191.                 DIBadMount(thisPoint, theEvent.message);    /* give format? dialog */
  192.                 DIUnload();    /* unload 'cuz we certainly don't need it */
  193.             }
  194.             break;
  195.         case updateEvt:    /* window update */
  196.             theWindow=(WindowPtr)theEvent.message;    /* which window? */
  197.             
  198.             BeginUpdate(theWindow);        /* means: "OK, we're dealing with this now" */
  199.             
  200.             if (thisWindowIsOurs)        /* one of ours?  see graphics.c */
  201.                 UpdateTheWindow(theData);
  202.             /* if not, could be our progress bar */
  203.             else if ((theWindow!=0L) && (theWindow==gProgressDlog))
  204.                 UpdateDialog(theWindow, theWindow->visRgn);
  205.             
  206.             EndUpdate(theWindow);        /* means: "OK, we're done updating now" */
  207.             break;
  208.         case activateEvt:    /* window activate or deactivate */
  209.             if (thisWindowIsOurs)        /* one of ours?  send message to window dispatch */
  210.                 ((**theData).dispatchProc)((WindowDataHandle)theData,
  211.                     ((theEvent.modifiers&activeFlag)!=0) ? kActivate : kDeactivate, 0L);
  212.             break;
  213.         case osEvt:            /* suspend or resume program execution (switch in/out) */
  214.             if (((theEvent.message>>24)&0x0FF)==suspendResumeMessage)
  215.             {
  216.                 /* keep track of whether we're in the background or foreground */
  217.                 gIsInBackground=((theEvent.message&resumeFlag)==0);
  218.                 
  219.                 if (gFrontWindowIsOurs)        /* send activate/deactivate to front window */
  220.                     ((**theData).dispatchProc)((WindowDataHandle)theData, gIsInBackground ?
  221.                         kDeactivate : kActivate, 0L);
  222.                 
  223.                 for (i=0; i<NUM_WINDOWS; i++)    /* send suspend/resume to all our */
  224.                     if (gTheWindow[i]!=0L)        /* windows that currently exist */
  225.                         ((**(gTheWindowData[i])).dispatchProc)((WindowDataHandle)gTheWindowData[i],
  226.                             gIsInBackground ? kSuspend : kResume, 0L);
  227.                 
  228.                 /* if we just came into the foreground and we have a pending error,
  229.                    now's the time to display it */
  230.                 if ((!gIsInBackground) && (gPendingResultCode!=allsWell))
  231.                 {
  232.                     if (gHasNotificationManager)
  233.                         NMRemove(&gMyNotification);        /* remove notification request */
  234.                     HandleError(gPendingResultCode, FALSE);    /* display alert, see error.c */
  235.                     gPendingResultCode=allsWell;        /* ...now it is */
  236.                 }
  237.             }
  238.             break;
  239.         case kHighLevelEvent:    /* apple event */
  240.             if (gHasAppleEvents)
  241.                 AEProcessAppleEvent(&theEvent);        /* see apple events.c */
  242.             break;
  243.     }
  244. }
  245.  
  246. void HandleMouseDown(EventRecord theEvent)
  247. {
  248.     WindowPtr            theWindow;
  249.     short                windowCode;
  250.     long                windSize;
  251.     GrafPtr                oldPort;
  252.     short                i;
  253.     Rect                sizeRect;
  254.     Boolean                gotone;
  255.     short                index;
  256.     unsigned long        dummy;
  257.     Point                theLocalPoint;
  258.     Boolean                thisWindowIsOurs;
  259.     ExtendedWindowDataHandle    theData;
  260.     
  261.     windowCode=FindWindow(theEvent.where, &theWindow);    /* which window? */
  262.  
  263.     thisWindowIsOurs=FALSE;
  264.     /* find out if the target window was one of ours */
  265.     if (theWindow!=0L)
  266.         for (index=0; ((index<NUM_WINDOWS) && (!thisWindowIsOurs)); index++)
  267.             thisWindowIsOurs=(theWindow==gTheWindow[index]);
  268.  
  269.     if (thisWindowIsOurs)    /* if target window is one of ours, get window data struct */
  270.     {
  271.         theData=(ExtendedWindowDataHandle)GetWRefCon(theWindow);
  272.         index=(**theData).windowIndex;
  273.     }
  274.     else index=-1;
  275.     
  276.     switch (windowCode)
  277.     {
  278.         case inMenuBar:        /* in menu bar; let system take over */
  279.             AdjustMenus();
  280.             HandleMenu(MenuSelect(theEvent.where));
  281.             break;
  282.         case inContent:        /* in window content */
  283.             if (FrontWindow() != theWindow)        /* maybe switch to different window */
  284.             {
  285.                 if (FrontWindow()==gProgressDlog)    /* but not if progress bar is up */
  286.                     SysBeep(7);
  287.                 else SelectWindow(theWindow);
  288.             }
  289.             else if (gFrontWindowIsOurs)    /* inform window dispatch of mousedown */
  290.             {
  291.                 theLocalPoint=theEvent.where;
  292.                 GlobalToLocal(&theLocalPoint);
  293. //                GetMouse(&theLocalPoint);    /* in window's local coordinates */
  294.                 dummy=theLocalPoint.h;        /* all this fiddling is so we can pass */
  295.                 dummy=dummy<<16;            /* the point (two integers) to the */
  296.                 dummy+=theLocalPoint.v;        /* dispatch procedure in an unsigned long */
  297.                 ((**theData).dispatchProc)((WindowDataHandle)theData, kMousedown, dummy);    /* go for it */
  298.             }
  299.             break;
  300.         case inSysWindow:    /* in system window (desk accessory) */
  301.             SystemClick(&theEvent, theWindow);    /* let the system deal with it */
  302.             break;
  303.         case inDrag:        /* in drag _region_, that is */
  304.             /* the accepted way to draw a window */
  305.             DragWindow(theWindow, theEvent.where, &((**GetGrayRgn()).rgnBBox));
  306.             if (thisWindowIsOurs)    /* update window bounds in window data struct */
  307.                 (**theData).windowBounds=(*(((WindowPeek)gTheWindow[index])->contRgn))->rgnBBox;
  308.             break;
  309.         case inGoAway:        /* close box */
  310.             /* the accepted way to track a close box attempt */
  311.             if (TrackGoAway(theWindow, theEvent.where))
  312.                 DoTheCloseThing((WindowPeek)theWindow);        /* see menus.c */
  313.             break;
  314.         case inGrow:        /* grow box */
  315.             /* the accepted way to grow a window */
  316.             sizeRect = screenBits.bounds;
  317.             OffsetRect(&sizeRect, sizeRect.left, sizeRect.top);
  318.             
  319.             windSize = GrowWindow(theWindow, theEvent.where, &sizeRect);
  320.             if (windSize != 0)
  321.             {
  322.                 GetPort(&oldPort);
  323.                 SetPort(theWindow);
  324.                 EraseRect(&theWindow->portRect);
  325.                 SizeWindow(theWindow, LoWord(windSize), HiWord(windSize), TRUE);
  326.                 InvalRect(&theWindow->portRect);
  327.                 SetPort(oldPort);
  328.             }
  329.             
  330.             if (thisWindowIsOurs)    /* update window bounds in window data struct */
  331.                 (**theData).windowBounds=(*(((WindowPeek)gTheWindow[index])->contRgn))->rgnBBox;
  332.             break;
  333.         case inZoomIn:        /* zoom box */
  334.         case inZoomOut:
  335.             /* the accepted way to track a zoom attempt */
  336.             if (TrackBox(theWindow, theEvent.where, windowCode))
  337.             {
  338.                 GetPort(&oldPort);
  339.                 SetPort(theWindow);
  340.                 ZoomWindow(theWindow, windowCode, FALSE);
  341.                 InvalRect(&theWindow->portRect);
  342.                 SetPort(oldPort);
  343.             }
  344.             
  345.             if (thisWindowIsOurs)    /* update window bounds in window data struct */
  346.                 (**theData).windowBounds=(*(((WindowPeek)gTheWindow[index])->contRgn))->rgnBBox;
  347.             break;
  348.     }
  349. }
  350.  
  351. void ShutDownEnvironment(void)
  352. {
  353.     SaveThePrefs();
  354.     ShutDownTheProgram();        /* program-specific cleanup */
  355.     ShutDownTheGraphics();        /* shell-specific clean-up */
  356.     CloseTheSoundChannel();        /* dispose of sound channel, if exists */
  357. }
  358.